package com.flbill.service.impl;

import com.flbill.common.utils.BaseContext;
import com.flbill.mapper.TransactionsMapper;
import com.flbill.mapper.UserMapper;
import com.flbill.pojo.dto.ReportDTO;
import com.flbill.pojo.entity.DataSE;
import com.flbill.pojo.vo.ExpenseReportVO;
import com.flbill.pojo.vo.IncomeReportVO;
import com.flbill.service.ReportService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import jakarta.servlet.http.HttpServletResponse;

@Service
public class ReportServiceImpl implements ReportService {
    private final TransactionsMapper transactionsMapper;
    private final UserMapper UserMapper;
    public ReportServiceImpl(TransactionsMapper transactionsMapper,  UserMapper UserMapper) {
        this.transactionsMapper = transactionsMapper;
        this.UserMapper = UserMapper;
    }
    @Transactional
    @Override
    public ExpenseReportVO expensePie(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
       ExpenseReportVO  expenseReportVO =new ExpenseReportVO();
       expenseReportVO.setActual_expense(transactionsMapper.ExpensePie(userId,dataSE.getStartDate(),dataSE.getEndDate()));
       expenseReportVO.setExpected_expense(UserMapper.PlanExpensePie(userId));
       return expenseReportVO;
    }

    @Transactional
    @Override
    public IncomeReportVO incomePie(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        IncomeReportVO incomeReportVO =new IncomeReportVO();
        incomeReportVO.setFixed_income(UserMapper.getFixedIncome(userId));
        incomeReportVO.setOther_income(transactionsMapper.IncomePie(userId,dataSE.getStartDate(),dataSE.getEndDate()));
        return incomeReportVO;
    }

    @Override
    public List<Map<String, Object>> expenseBar(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        return transactionsMapper.ExpenseBar(userId, dataSE.getStartDate(), dataSE.getEndDate());
    }

    @Override
    public List<Map<String, Object>> incomeBar(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        return transactionsMapper.IncomeBar(userId, dataSE.getStartDate(), dataSE.getEndDate());
    }

    @Override
    public List<com.flbill.pojo.entity.Income> incomeDetails(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        return transactionsMapper.selectIncomeDetails(userId, dataSE.getStartDate(), dataSE.getEndDate());
    }

    @Override
    public List<com.flbill.pojo.entity.Expense> expenseDetails(ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        return transactionsMapper.selectExpenseDetails(userId, dataSE.getStartDate(), dataSE.getEndDate());
    }

    @Override
    public java.util.List<com.flbill.pojo.vo.MonthReportVO> monthSummary(com.flbill.pojo.dto.ReportDTO reportDTO) {
        Integer userId = BaseContext.getCurrentId();
        DataSE dataSE = getSE(reportDTO);
        java.time.LocalDate start = dataSE.getStartDate();
        java.time.LocalDate end = dataSE.getEndDate();
        java.util.List<com.flbill.pojo.vo.MonthReportVO> result = new java.util.ArrayList<>();
        if (start == null || end == null) return result;
        java.time.LocalDate iter = start.withDayOfMonth(1);
        while (!iter.isAfter(end)) {
            java.time.LocalDate monthStart = iter;
            java.time.LocalDate monthEnd = iter.withDayOfMonth(iter.lengthOfMonth());
            if (monthEnd.isAfter(end)) monthEnd = end;
            // 查询总收入
            Float totalIncome = transactionsMapper.IncomePie(userId, monthStart, monthEnd);
            // 查询总支出
            Float totalExpense = transactionsMapper.ExpensePie(userId, monthStart, monthEnd);
            // 查询期望支出
            Float expectedExpense = UserMapper.PlanExpensePie(userId);
            // 是否超期望
            boolean isOver = (expectedExpense != null && totalExpense != null) ? totalExpense > expectedExpense : false;
            com.flbill.pojo.vo.MonthReportVO vo = new com.flbill.pojo.vo.MonthReportVO();
            vo.setMonth(monthStart.toString().substring(0,7));
            vo.setTotalIncome(totalIncome == null ? 0 : totalIncome);
            vo.setTotalExpense(totalExpense == null ? 0 : totalExpense);
            vo.setExpectedExpense(expectedExpense == null ? 0 : expectedExpense);
            vo.setIsOverExpected(isOver);
            result.add(vo);
            iter = iter.plusMonths(1);
        }
        return result;
    }

    private DataSE getSE(ReportDTO reportDTO){
        DataSE dataSE = new DataSE();
        String timeRange = reportDTO.getTimeRange();
        if(reportDTO.getStartDate()!=null && reportDTO.getEndDate()!=null){
            dataSE.setStartDate(reportDTO.getStartDate());
            dataSE.setEndDate(reportDTO.getEndDate());
        }else if (timeRange != null) {
            LocalDate now = LocalDate.now();
            switch (timeRange) {
                case "week":
                    dataSE.setEndDate(now);
                    dataSE.setStartDate(now.minusDays(6)); // 包含今天共7天
                    break;
                case "month":
                    dataSE.setStartDate(now.withDayOfMonth(1));
                    dataSE.setEndDate(now.withDayOfMonth(now.lengthOfMonth()));
                    break;
                case "year":
                    dataSE.setStartDate(now.withDayOfYear(1));
                    dataSE.setEndDate(now.withDayOfYear(now.lengthOfYear()));
                    break;
                default:
                    // 默认本月
                    dataSE.setStartDate(now.withDayOfMonth(1));
                    dataSE.setEndDate(now.withDayOfMonth(now.lengthOfMonth()));
            }
        } else {
            // 全部为空，默认本月
            LocalDate now = LocalDate.now();
            dataSE.setStartDate(now.withDayOfMonth(1));
            dataSE.setEndDate(now.withDayOfMonth(now.lengthOfMonth()));
        }
        return dataSE;
    }

}
